#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#include "MSTK.h"
#include <mpi.h>

int main(int argc, char *argv[]) {
  int  i, dim;
  char mname[256],filename[256], buf[256],attr_name[256],subfilename[256];
  int num, rank;

  if(argc == 1) {
    printf("code for the example in the manual\n");
    printf("usage: mpirun -np %s 4 meshname -d 2\n",argv[0]);
    exit(-1);
  }
  
  /* Initialize MSTK */
  MSTK_Init();  
  /* initialize MPI */
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&num);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);

  /* Load the mesh */
  strcpy(mname,argv[1]);
  strcpy(filename,mname);
  strcat(filename,".mstk");
  dim = atoi(argv[3]);


  Mesh_ptr recv_mesh = MESH_New(UNKNOWN_REP);
  MSTK_Mesh_Scatter(&recv_mesh, filename, dim, 1, 1, rank, num, MPI_COMM_WORLD);
  /* now recv_mesh is the mesh partition */


  /* do some operation on recv_mesh */
  strcpy(attr_name,"face_indicater");
  MAttrib_ptr attrib = MAttrib_New(recv_mesh,attr_name,INT,MFACE);
  MVertex_ptr mv;
  MFace_ptr mf;
  List_ptr mfverts;
  double xyz[3];
  int idx = 0;
  while(mf = MESH_Next_Face(recv_mesh,&idx)) {
    if(MF_PType(mf) == PGHOST)
      MEnt_Set_AttVal(mf,attrib,2,0,NULL);      
    else {
      MEnt_Set_AttVal(mf,attrib,0,0,NULL);      
      mfverts = MF_Vertices(mf,1,0);
      for(i = 0; i < List_Num_Entries(mfverts); i++) {
	mv = List_Entry(mfverts,i);
	MV_Coords(mv,xyz);
	if( (xyz[0]-0.5)*(xyz[0]-0.5) + (xyz[1]-0.5)*(xyz[1]-0.5) < 0.25*0.25 ) {
	  MEnt_Set_AttVal(mf,attrib,1,0,NULL);
	  break;
	}
      }
      List_Delete(mfverts);
    }
  }

  strcpy(subfilename,mname);
  itoa(rank,buf);
  strcat(subfilename,buf);
  strcat(subfilename,"-before.mstk");
  PMESH_WriteToFile(recv_mesh,subfilename,MESH_RepType(recv_mesh));
 
  /* update attribute values */
  MSTK_UpdateAttr(recv_mesh,rank,num,MPI_COMM_WORLD);


  strcpy(subfilename,mname);
  itoa(rank,buf);
  strcat(subfilename,buf);
  strcat(subfilename,"-after.mstk");
  PMESH_WriteToFile(recv_mesh,subfilename,MESH_RepType(recv_mesh));
 
  MPI_Finalize();
  return 1;
}

